babl: add ~ variants to gray color models
authorØyvind Kolås <pippin@gimp.org>
Wed, 20 Jun 2018 18:43:53 +0000 (20:43 +0200)
committerØyvind Kolås <pippin@gimp.org>
Wed, 20 Jun 2018 18:50:04 +0000 (20:50 +0200)
We do not add premultiplied sRGB trc variants even if this exists for RGB
since it is the type of premultiplied alpha cairo expects. The less code
that does non-linear compositing the better, excluding some possibilities
also reduces the combinatorial overhead of finding conversion paths in babl.

babl/babl-ids.h
babl/base/formats.c
babl/base/model-gray.c

index 324b240587c22042697b5673d6c2aff828bfee82..a35efd2dad1977a8a6b4b4cd793480a49e6acca5 100644 (file)
@@ -47,10 +47,10 @@ enum {
   BABL_RGBA_PREMULTIPLIED,
   BABL_MODEL_GRAY_NONLINEAR,
   BABL_MODEL_GRAY_NONLINEAR_ALPHA,
-  BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED,
-  BABL_GRAY_PERCEPTUAL,
-  BABL_GRAY_PERCEPTUAL_ALPHA,
-  BABL_GRAY_PERCEPTUAL_ALPHA_PREMULTIPLIED,
+  BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED,
+  BABL_MODEL_GRAY_PERCEPTUAL,
+  BABL_MODEL_GRAY_PERCEPTUAL_ALPHA,
+  BABL_MODEL_GRAY_PERCEPTUAL_ALPHA_PREMULTIPLIED,
   BABL_RGB_NONLINEAR,
   BABL_RGBA_NONLINEAR,
   BABL_RGBA_NONLINEAR_PREMULTIPLIED,
@@ -73,6 +73,7 @@ enum {
   BABL_RED_MUL_ALPHA,
   BABL_GREEN_MUL_ALPHA,
   BABL_BLUE_MUL_ALPHA,
+  BABL_GRAY_PERCEPTUAL,
   BABL_GRAY_NONLINEAR,
   BABL_GRAY_NONLINEAR_MUL_ALPHA,
   BABL_RED_NONLINEAR,
index 97e6e8b28bced2026cf374c5e8d95c541fabda84..7affcc56158d613a036b4979b81d9352b8730fb1 100644 (file)
@@ -111,7 +111,7 @@ babl_formats_init (void)
     babl_component_from_id (BABL_ALPHA),
     NULL);
   babl_format_new (
-    babl_model_from_id (BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
+    babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
     babl_type_from_id (BABL_FLOAT),
     babl_component_from_id (BABL_GRAY_NONLINEAR_MUL_ALPHA),
     babl_component_from_id (BABL_ALPHA),
@@ -128,7 +128,7 @@ babl_formats_init (void)
     babl_component_from_id (BABL_ALPHA),
     NULL);
   babl_format_new (
-    babl_model_from_id (BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
+    babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
     babl_type_from_id (BABL_U16),
     babl_component_from_id (BABL_GRAY_NONLINEAR_MUL_ALPHA),
     babl_component_from_id (BABL_ALPHA),
@@ -145,7 +145,7 @@ babl_formats_init (void)
     babl_component_from_id (BABL_ALPHA),
     NULL);
   babl_format_new (
-    babl_model_from_id (BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
+    babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
     babl_type_from_id (BABL_U8),
     babl_component_from_id (BABL_GRAY_NONLINEAR_MUL_ALPHA),
     babl_component_from_id (BABL_ALPHA),
index 47a875b6f9e4d4c29be3dd14a811994930a15818..ea1ca98cb2c47321a721ac9641a128e7c45855cb 100644 (file)
@@ -19,8 +19,7 @@
 #include "config.h"
 #include <stdlib.h>
 
-#include "babl-classes.h"
-#include "babl.h"
+#include "babl-internal.h"
 #include "babl-ids.h"
 #include "math.h"
 #include "babl-base.h"
@@ -64,6 +63,12 @@ components (void)
     "id", BABL_GRAY_NONLINEAR_MUL_ALPHA,
     "luma",
     NULL);
+
+  babl_component_new (
+    "Y~",
+    "id", BABL_GRAY_PERCEPTUAL,
+    "luma",
+    NULL);
 }
 
 static void
@@ -87,9 +92,8 @@ models (void)
     babl_component_from_id (BABL_ALPHA),
     NULL);
 
-
   babl_model_new (
-    "id", BABL_GRAY_NONLINEAR,
+    "id", BABL_MODEL_GRAY_NONLINEAR,
     babl_component_from_id (BABL_GRAY_NONLINEAR),
     NULL);
 
@@ -100,12 +104,23 @@ models (void)
     NULL);
 
   babl_model_new (
-    "id", BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED,
+    "id", BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED,
     babl_component_from_id (BABL_GRAY_NONLINEAR_MUL_ALPHA),
     babl_component_from_id (BABL_ALPHA),
     NULL);
-}
 
+  babl_model_new (
+    "id", BABL_MODEL_GRAY_PERCEPTUAL,
+    babl_component_from_id (BABL_GRAY_PERCEPTUAL),
+    NULL);
+
+  babl_model_new (
+    "id", BABL_MODEL_GRAY_PERCEPTUAL_ALPHA,
+    babl_component_from_id (BABL_GRAY_PERCEPTUAL),
+    babl_component_from_id (BABL_ALPHA),
+    NULL);
+
+}
 
 static void
 rgba_to_graya (Babl *conversion,
@@ -171,6 +186,8 @@ rgba_to_gray (Babl *conversion,
     }
 }
 
+static const Babl *perceptual_trc = NULL;
+
 static void
 rgb_to_gray_nonlinear (Babl  *conversion,
                        int    src_bands,
@@ -254,6 +271,88 @@ gray_nonlinear_to_rgb (Babl *conversion,
     }
 }
 
+static void
+rgb_to_gray_perceptual (Babl  *conversion,
+                        int    src_bands,
+                        char **src,
+                        int   *src_pitch,
+                        int    dst_bands,
+                        char **dst,
+                        int   *dst_pitch,
+                        long   n)
+{
+  const Babl *space = babl_conversion_get_destination_space (conversion);
+  const Babl *trc = perceptual_trc;
+  double RGB_LUMINANCE_RED   = space->space.RGBtoXYZ[3];
+  double RGB_LUMINANCE_GREEN = space->space.RGBtoXYZ[4];
+  double RGB_LUMINANCE_BLUE  = space->space.RGBtoXYZ[5];
+
+  BABL_PLANAR_SANITY
+  while (n--)
+    {
+      double red, green, blue;
+      double luminance, alpha;
+
+      red   = *(double *) src[0];
+      green = *(double *) src[1];
+      blue  = *(double *) src[2];
+      if (src_bands > 3)
+        alpha = *(double *) src[3];
+      else
+        alpha = 1.0;
+
+      luminance = red   * RGB_LUMINANCE_RED +
+                  green * RGB_LUMINANCE_GREEN +
+                  blue  * RGB_LUMINANCE_BLUE;
+      *(double *) dst[0] = babl_trc_from_linear (trc, luminance);
+
+      if (dst_bands == 2)
+        *(double *) dst[1] = alpha;
+
+      BABL_PLANAR_STEP
+    }
+}
+
+static void
+gray_perceptual_to_rgb (Babl *conversion,
+                        int    src_bands,
+                        char **src,
+                        int   *src_pitch,
+                        int    dst_bands,
+                        char **dst,
+                        int   *dst_pitch,
+                        long   n)
+{
+  const Babl *trc = perceptual_trc;
+
+  BABL_PLANAR_SANITY
+  while (n--)
+    {
+      double luminance;
+      double red, green, blue;
+      double alpha;
+
+      luminance = babl_trc_to_linear (trc, *(double *) src[0]);
+      red       = luminance;
+      green     = luminance;
+      blue      = luminance;
+      if (src_bands > 1)
+        alpha = *(double *) src[1];
+      else
+        alpha = 1.0;
+
+      *(double *) dst[0] = red;
+      *(double *) dst[1] = green;
+      *(double *) dst[2] = blue;
+
+      if (dst_bands > 3)
+        *(double *) dst[3] = alpha;
+
+      BABL_PLANAR_STEP
+    }
+}
+
+
 static void
 graya_to_rgba (Babl *conversion,
                char *src,
@@ -516,10 +615,10 @@ gray_nonlinear_premultiplied2rgba (Babl *conversion,
     }
 }
 
-
 static void
 conversions (void)
 {
+  perceptual_trc = babl_trc ("sRGB");
   babl_conversion_new (
     babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR),
     babl_model_from_id (BABL_RGBA),
@@ -550,7 +649,7 @@ conversions (void)
 
 
   babl_conversion_new (
-    babl_model_from_id (BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
+    babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
     babl_model_from_id (BABL_RGBA),
     "linear", gray_nonlinear_premultiplied2rgba,
     NULL
@@ -558,11 +657,42 @@ conversions (void)
 
   babl_conversion_new (
     babl_model_from_id (BABL_RGBA),
-    babl_model_from_id (BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
+    babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
     "linear", rgba2gray_nonlinear_premultiplied,
     NULL
   );
 
+
+
+  babl_conversion_new (
+    babl_model_from_id (BABL_MODEL_GRAY_PERCEPTUAL),
+    babl_model_from_id (BABL_RGBA),
+    "planar", gray_perceptual_to_rgb,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_model_from_id (BABL_RGBA),
+    babl_model_from_id (BABL_MODEL_GRAY_PERCEPTUAL),
+    "planar", rgb_to_gray_perceptual,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_model_from_id (BABL_MODEL_GRAY_PERCEPTUAL_ALPHA),
+    babl_model_from_id (BABL_RGBA),
+    "planar", gray_perceptual_to_rgb,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_model_from_id (BABL_RGBA),
+    babl_model_from_id (BABL_MODEL_GRAY_PERCEPTUAL_ALPHA),
+    "planar", rgb_to_gray_perceptual,
+    NULL
+  );
+
+
   babl_conversion_new (
     babl_model_from_id (BABL_GRAY),
     babl_model_from_id (BABL_RGBA),
@@ -647,7 +777,7 @@ formats (void)
     babl_component_from_id (BABL_ALPHA),
     NULL);
   babl_format_new (
-    babl_model_from_id (BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
+    babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
     babl_type_from_id (BABL_HALF),
     babl_component_from_id (BABL_GRAY_NONLINEAR_MUL_ALPHA),
     babl_component_from_id (BABL_ALPHA),
@@ -683,7 +813,7 @@ formats (void)
     babl_component_from_id (BABL_ALPHA),
     NULL);
   babl_format_new (
-    babl_model_from_id (BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
+    babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
     babl_type ("u15"),
     babl_component_from_id (BABL_GRAY_NONLINEAR_MUL_ALPHA),
     babl_component_from_id (BABL_ALPHA),
@@ -718,7 +848,7 @@ formats (void)
     babl_component_from_id (BABL_ALPHA),
     NULL);
   babl_format_new (
-    babl_model_from_id (BABL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
+    babl_model_from_id (BABL_MODEL_GRAY_NONLINEAR_ALPHA_PREMULTIPLIED),
     babl_type_from_id (BABL_U32),
     babl_component_from_id (BABL_GRAY_NONLINEAR_MUL_ALPHA),
     babl_component_from_id (BABL_ALPHA),